'''
Created on Oct 15, 2012

@author: petrina
'''
import logging
import numpy

class Indiutils(object):
    '''
    Calculation tools for the indicator calculation
    '''  
    
    def p5_speed(self, timeseries):
        '''
        calculates the 5th percentile of speeds using the standard deviation from the timeseries for every time interval.
        
        If there is no data on a specific time interval the value is set to None.
        Following formula is applied to calculate the P:
            P05_v_i = v_avg_i - 1.96 * std_i
                - p05_v_i ... 5th percentile of speeds for the time interval i
                - v_avg ... harmonic speed provided by the Agg_record-object
                - std_i ... standard deviation at the time interval i
                
        @return: values (numeric value of the percentile or None) in a list for every interval
        '''
        
        if timeseries is not None: 
            p = [timeseries[i][0].speed_avg - 1.96 * timeseries[i][0].std if len(timeseries[i]) > 0 else None for i in timeseries]
            if p.count(None) > 0:
                logging.error("Indiutils: %d missing value(s) in timeseries - cannot find P5 of speeds"%p.count(None)) 
            return p
        else:
            logging.error("Indiutils: cannot calculate P05 of speeds because there are no timeseries")
            #Indicator_exception("cannot calculate P95 of travel times because there are no timeseries")
            return None
 

    def p95_tt(self, timeseries, length):
        '''
        calculates the 95th percentile of travel times using the standard deviation from the timeseries for every time interval.
        
        If there is no data on a specific time interval the value is set to None.
        If ther are no timeseries the method will raise an error. 
        Following formula is applied to calculate the P:
            P95_tt_i = l/P05_v_i
            P05_v_i = v_avg_i - 1.96 * std_i
            
                - P95_tt_i ... 95th percentile travel time for the time interval i
                - p05_v_i ... 5th percentile of speeds for the time interval i
                - l ... link-length
                - v_avg ... harmonic speed provided by the Agg_record-object
                - std_i ... standard deviation at the time interval i
        
        @return: values (numeric value of the percentile or None) in a list for every interval
        '''
        
        if timeseries is not None:
            p = [None if p5 is None else length/(p5+0.0) for p5 in self.p5_speed(timeseries)]
            if timeseries.is_kph: 
                p = [None if ptt is None else ptt*3.6 for ptt in p]

            if p.count(None) > 0:
                logging.error("Indiutils: %d missing value(s) in timeseries - cannot find P95 of travel times "%p.count(None))

            return p
        else:
            logging.error("Indiutils: cannot calculate P95 of travel times because there are no timeseries")
            #Indicator_exception("cannot calculate P95 of travel times because there are no timeseries")   
            return None
    
    
    def stddev_speed(self, timeseries):
        '''
        returns the standard deviation of speeds using the standard deviation from the timeseries for every time interval.
        
        If the timeseries-object is None an error will be raised. If there is no data on a specific time interval,
        the value on this interval is None.

        @return: values (numeric value of the standard deviation or None) in a list for every interval
        '''
        
        if timeseries is not None:         
            stddev = [timeseries[i][0].std if len(timeseries[i]) > 0 else None for i in timeseries]
            if stddev.count(None) > 0:
                logging.error("Indiutils: %d missing value(s) in timeseries - cannot find standard deviation of speeds"%stddev.count(None))
            
            return stddev
        
        else:
            logging.error("Indiutils: cannot calculate the standard deviation of speeds because there are no timeseries")
            #Indicator_exception("cannot calculate the standard deviation of speeds because there are no timeseriess")
            return None

    def calc_stddev_of(self, records, attribute):
        '''
        calculates the standard deviation for a given attribute for all intervals as list
        
        @param records: Record_list with data for each time interval 
        @param attribute: attribute of agg_record (e.g. speed, traveltime) as string 
        '''
        
        int_data = []
        for _, list in records.items():
            data = [getattr(rec, attribute) for rec in list]
            
            # mean for every interval (None if the interval is empty)
            int_data.append(None if len(data) == 0 else numpy.std(data, ddof=1)) 
                
        return int_data


    def calc_average_of(self, records, attribute):
        '''
        calculates the average for a given attribute for all intervals as list
        
        @param records: Record_list with data for each time interval 
        @param attribute: attribute of agg_record (e.g. speed, traveltime) as string 
        '''
        
        int_data = []
        for _, list in records.items():
            data = [getattr(rec, attribute) for rec in list]
            
            # mean for every interval (None if the interval is empty)
            int_data.append(None if len(data) == 0 else numpy.mean(data)) 
                
        return int_data